<?php
# oauth library for validating requests
require_once 'oauth-library/OAuthServer.php';
require_once 'oauth-library/OAuthStore.php';

# rest controller
require_once APPPATH . '/libraries/REST_Controller.php';

/*
class Status
{
	const ERR_NO_TASK_ID = 100;
	const ERR_NO_CONTENT = 101;
}
*/

class Api extends REST_Controller
{
	const STATUS_OK = 0;
	const STATUS_GENERAL_ERROR = 100;
	const STATUS_INVALID_TASK_ID = 101;
	const STATUS_NO_CONTENT = 102;
	const STATUS_ERR_DELETE_TASKS = 104;
	const STATUS_INVALID_ACCOUNT_ID = 105;
	
	const DEFAULT_TASKS_PER_PAGE = 20;
	
	private $db_conn = null;
	private $user_id = null;
	
	function Api()
	{
		parent::__construct();
		
		include(APPPATH.'config/database'.EXT);
		
		# the oauth library requires basic mysql connection resource connection for db access;
		# the built in codeigniter wrapper is no good
		($db_conn = mysql_connect($db['default']['hostname'], $db['default']['username'], $db['default']['password'])) 
			|| die(mysql_error());
		mysql_select_db($db['default']['database'], $db_conn) || die(mysql_error());
		mysql_query('SET NAMES utf8');

		try
		{
			OAuthStore::instance('MySQL', array('conn' => $db_conn));
			
			$server = new OAuthServer();
			if (!$this->user_id = $server->verify())
			{
				header('HTTP/1.1 401 Unauthorized');
				header('Content-Type: text/plain');
				
				echo "OAuth Verification Failed";
				exit;
			}
			
			log_message('debug', 'user id = ' . $this->user_id);
		}
		catch(Exception $e)
		{
			header('HTTP/1.1 500 Internal Server Error');
			header('Content-Type: text/plain');
			echo $e->getMessage();
			exit;
		}
	}
	
	
	public function tasks_get()
	{
		$this->load->model('Tasks_model', 'tasks');
		
		# check if only one specific task is requested
		if( (int)$this->get('id') > 0 )
		{
			$task = $this->tasks->getTask($this->user_id, (int)$this->get('id'));
			$this->response($task, 200);
			return;
		}
		# check if count of tasks is requested
		elseif( $this->get('count') )
		{
			$count = $this->tasks->tasksCount($this->user_id, $this->get('count'));
			$this->response($count, 200);
			return;
		}
		# check if paging is requested
		elseif($this->get('page') && $this->get('pagesize'))
		{
			$page = (int)$this->get('page');
			$size = (int)$this->get('pagesize');
			$start = $page * $size;
		}
		else
		{
			$start = 0;
			$size = self::DEFAULT_TASKS_PER_PAGE;
		}
		
		# get tag if available, if not it will be ignored
		$tag_id = (int)$this->get('tag');
		
		$tasks = $this->tasks->getTasks($this->user_id, $tag_id, $start, $size);
		
		$this->response($tasks, 200);
	}
	
	# create new task
	public function tasks_put()
	{
		$this->load->model('Tasks_model', 'tasks');
		
		$content = $this->put('content');
		if(strlen($content) == 0)
		{
			$this->response($this->buildResponse(self::STATUS_NO_CONTENT), 400);
			return;
		}
		
		$tag_id = (int)$this->put('tag_id');
		$this->tasks->insert($this->user_id, $content, $tag_id);
		
		$this->response($this->buildResponse(self::STATUS_OK), 201);
	}
	
	
	public function tasks_delete()
	{
		$task_ids = $this->delete('id');
		$task_ids = trim($task_ids, ',');
		
		# validate values for task ids - they should be only numbers and commas
		if(!preg_match('/^[0-9,]+$/i', $task_ids))
		{
			$this->response($this->buildResponse(self::STATUS_INVALID_TASK_ID), 400);
			return;
		}

		$this->load->model('Tasks_model', 'tasks');
		if(!$this->tasks->deleteMultiple($this->user_id, $task_ids))
		{
			$this->response($this->buildResponse(self::STATUS_ERR_DELETE_TASKS), 500);
			return;
		}
		
		$this->response($this->buildResponse(self::STATUS_OK), 200);
	}
	
	# update existing task
	public function tasks_post()
	{
		$task_id = (int)$this->post('id');
		if($task_id == 0)
		{
			$this->response($this->buildResponse(self::STATUS_INVALID_TASK_ID), 400);
			return;
		}
		
		$this->load->model('Tasks_model', 'tasks');
		
		$task = new stdClass();
		$task->id = $task_id;
		
		if(isset($_POST['content']))
		{
			$content = $this->post('content');
			if(strlen($content) == 0)
			{
				$this->response($this->buildResponse(self::STATUS_NO_CONTENT), 400);
				return;
			}
						
			$task->content = $content;
			$this->tasks->save($this->user_id, $task);
		}
		
		if(isset($_POST['tags']))
		{
			$tags = $this->post('tags');
			$tags = trim($tags, ',');
			if(!empty($tags) && strlen($tags) > 0)
			{
				$tags = explode(',', $tags); # make array with tag names elements
				for($i=0; $i < count($tags); $i++) {
					$tags[$i] = substr($tags[$i], 0, MAX_TAG_LENGTH);
				}
			}
			else
			{
				# all task tags will be deleted in this case
				$tags = ''; 
			}
			
			$this->tasks->saveTags($this->user_id, $task->id, $tags);
		}
		
		if(isset($_POST['duedate']))
		{
			$duedate = (int)$this->post('duedate');
			$this->tasks->setDuedate($this->user_id, $task->id, $duedate);
		}
		
		if(isset($_POST['priority']))
		{
			$priority = (int)$this->post('priority');
			$this->tasks->priority($this->user_id, $task->id, $priority);
		}
		
		if(isset($_POST['state']))
		{
			$state = (int)$this->post('state');	
			$this->tasks->setState($this->user_id, $task->id, $state);
		}

		$this->response($this->buildResponse(self::STATUS_OK), 200);
	}
	
	
	public function tags_get()
	{
		$this->load->model('Tasks_model', 'tasks');		
		$tags = $this->tasks->getTags($this->user_id);
		$this->response($tags, 200);
	}
	
	/*
	public function account_get()
	{
		$user_id = (int)$this->post('id');
		if($user_id == 0 || $user_id != $this->user_id)
		{
			$this->response($this->buildResponse(self::STATUS_INVALID_ACCOUNT_ID), 400);
			return;
		}		
	}
	*/
	
	public function ping_get()
	{
		$this->response($this->buildResponse(self::STATUS_OK), 200);
	}
	
	
	public function buildResponse($statusCode)
	{
		$status = array();
		switch($statusCode)
		{
			case self::STATUS_OK:
				$status['code'] = self::STATUS_OK;
				$status['message'] = 'OK';
				break;
				
			case self::STATUS_NO_CONTENT:
				$status['code'] = self::STATUS_NO_CONTENT;
				$status['message'] = 'Error: content parameter is empty';
				break;
				
			case self::STATUS_INVALID_TASK_ID:
				$status['code'] = self::STATUS_INVALID_TASK_ID;
				$status['message'] = 'Error: invalid task id parameter';
				break;
				
			case self::STATUS_ERR_DELETE_TASKS:
				$status['code'] = self::STATUS_ERR_DELETE_TASKS;
				$status['message'] = 'Error: could not delete task(s)';
				break;
				
			case self::STATUS_INVALID_ACCOUNT_ID:
				$status['code'] = self::STATUS_INVALID_ACCOUNT_ID;
				$status['message'] = 'Error: invalid account id parameter';
				break;
				
			default:
				$status['code'] = self::STATUS_GENERAL_ERROR;
				$status['message'] = 'Error: could not complete the operation';
				break;
		}
		
		return array('status' => $status);
	}
}